package com.alks.function.service.async;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alks.common.utils.DateUtils;
import com.alks.common.utils.beanutils.StringUtils;
import com.alks.common.utils.export.dto.MockMultipartFile;
import com.alks.common.utils.export.service.FileExportTask;
import com.alks.function.data.vo.produce.ReportMonthVo;
import com.alks.function.handler.excel.ReportMonthCXHandler;
import org.springframework.http.MediaType;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: chen
 * @date: 2025/1/8
 * @description:
 */
public class LastFileExport extends FileExportTask {

    private Date startTime;

    private List<ReportMonthVo> putIntoList;

    private List<ReportMonthVo> outPutLIst;

    public LastFileExport(Date startTime, List<ReportMonthVo> putIntoList, List<ReportMonthVo> outPutLIst) {
        super();
        this.startTime = startTime;
        this.putIntoList = putIntoList;
        this.outPutLIst = outPutLIst;
    }

    @Override
    protected MockMultipartFile generateFile(String fileName) throws Exception {
        MockMultipartFile multipartFile = null;
        // 获取月天数据并排序
        List<Integer> days = DateUtils.getDaysOfMonth(startTime)
                .stream()
                .sorted().collect(Collectors.toList());

        String sheet1 = "成型投料明细";
        String sheet2 = "成型产出明细";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月");
        String date = sdf.format(startTime);
        String sheetName1 = String.format("%s份%s表", date, sheet1);
        String sheetName2 = String.format("%s份%s表", date, sheet2);

        List<Integer> merge1 = new ArrayList<>();
        List<Integer> merge2 = new ArrayList<>();
        List<List<Object>> data1 = initData(putIntoList, days, sheetName1, merge1, 1);
        List<List<Object>> data2 = initData(outPutLIst, days, sheetName2, merge2, 2);

        ExcelWriter excelWriter = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            excelWriter = EasyExcel.write(outputStream)
                    .registerWriteHandler(new ReportMonthCXHandler(merge1, merge2))
                    .build();
            excelWriter.write(data1, EasyExcel.writerSheet(0, sheet1).build());
            excelWriter.write(data2, EasyExcel.writerSheet(1, sheet2).build());

        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            //关闭流
            assert excelWriter != null;
            excelWriter.finish();

            multipartFile = new MockMultipartFile(fileName, fileName, MediaType.MULTIPART_FORM_DATA_VALUE, new ByteArrayInputStream(outputStream.toByteArray()));
            outputStream.close();
        }
        return multipartFile;
    }


    private List<List<Object>> initData(List<ReportMonthVo> dataList, List<Integer> days, String sheetName,
                                        List<Integer> merge, Integer type) {
        List<List<Object>> data = new ArrayList<>();
        Map<String, List<ReportMonthVo>> putIntoMap = dataList.stream()
                .collect(Collectors.groupingBy(ReportMonthVo::getLine));

        String typeStr = type == 1 ? "投料" : "产出";

        List<Object> head = new ArrayList<>();
        head.add("指令");
        head.add("型体");
        head.add("品牌");
        head.add("订单数");
        head.addAll(days);
        head.add("合计");
        head.add("上月" + typeStr);
        head.add(typeStr + "欠数");
        data.add(Collections.nCopies(head.size(), sheetName));

        Map<String, Integer> countAllMap = new HashMap<>();
        for (String line : putIntoMap.keySet()) {
            data.add(Collections.singletonList(line));
            data.add(head);

            if (putIntoMap.get(line).isEmpty()) continue;
            Map<String, List<ReportMonthVo>> lotMap = putIntoMap.get(line).stream()
                    .collect(Collectors.groupingBy(ReportMonthVo::getLotNo));
            Map<String, Integer> countMap = new HashMap<>();
            for (String lotNo : lotMap.keySet()) {
                List<ReportMonthVo> list = lotMap.get(lotNo);
                if (list.isEmpty()) continue;
                List<Object> item = new ArrayList<>();
                item.add(lotNo);
                item.add(list.get(0).getStyle());
                item.add(list.get(0).getCustom());
                item.add(list.get(0).getOrderQty());

                // 日数据
                Map<Integer, ReportMonthVo> dayMap = list.stream()
                        .collect(Collectors.toMap(e-> DateUtils.getDayOfMonth(e.getDate()), e->e));
                int count = 0;
                int totalCount = 0;
                int orderQty = 0;
                Integer lastMonthCount = null;
                for (Integer day : days) {
                    ReportMonthVo vo = dayMap.get(day);
                    if (vo == null) {
                        item.add(null);
                        continue;
                    }
                    item.add(vo.getQty());
                    count += vo.getQty();
                    lastMonthCount = vo.getLastMothCount();
                    orderQty = vo.getOrderQty();
                    totalCount = vo.getTotalCount();

                    if (countMap.containsKey(day.toString())) {
                        countMap.put(day.toString(), countMap.get(day.toString()) + vo.getQty());
                    } else {
                        countMap.put(day.toString(), vo.getQty());
                    }
                    if (countAllMap.containsKey(day.toString())) {
                        countAllMap.put(day.toString(), countAllMap.get(day.toString()) + vo.getQty());
                    } else {
                        countAllMap.put(day.toString(), vo.getQty());
                    }
                }
                item.add(count);
                item.add(lastMonthCount);
                item.add(orderQty - totalCount);
                data.add(item);
                if (countMap.containsKey("total")) {
                    countMap.put("total", countMap.get("total") + count);
                } else {
                    countMap.put("total", count);
                }
                if (countAllMap.containsKey("total")) {
                    countAllMap.put("total", countAllMap.get("total") + count);
                } else {
                    countAllMap.put("total", count);
                }
            }
            List<Object> statistics = new ArrayList<>();
            statistics.add("小计");
            statistics.add(null);
            statistics.add(null);
            statistics.add(null);
            for (Integer day : days) {
                statistics.add(countMap.get(day.toString()));
            }
            statistics.add(countMap.get("total"));
            statistics.add(null);
            statistics.add(null);
            data.add(statistics);

            List<Object> cl1 = new ArrayList<>();
            cl1.add("本月生产型体汇总");
            cl1.add("型体");

            List<Object> cl2 = new ArrayList<>();
            cl2.add("本月生产型体汇总");
            cl2.add("投料数量");

            Map<String, List<ReportMonthVo>> styleMap = putIntoMap.get(line).stream()
                    .filter(e-> !StringUtils.isEmpty(e.getStyle()))
                    .collect(Collectors.groupingBy(ReportMonthVo::getStyle));
            for (String style : styleMap.keySet()) {
                cl1.addAll(Collections.nCopies(2, style));
                cl2.addAll(Collections.nCopies(2, styleMap.get(style).stream().mapToInt(ReportMonthVo::getQty).sum()));
            }

            //固定样式
            int cl1Padding = head.size() - cl1.size();
            if (cl1Padding > 0) {
                cl1.addAll(Collections.nCopies(cl1Padding, null));
            }
            int cl2Padding = head.size() - cl2.size();
            if (cl2Padding > 0) {
                cl2.addAll(Collections.nCopies(cl2Padding, null));
            }
            data.add(cl1);
            data.add(cl2);
            merge.add(data.size()-2);
            merge.add(data.size()-1);
            data.add(Collections.singletonList(null));
        }
        List<Object> statistics = new ArrayList<>();
        statistics.add("总计");
        statistics.add(null);
        statistics.add(null);
        statistics.add(null);
        for (Integer day : days) {
            statistics.add(countAllMap.get(day.toString()));
        }
        statistics.add(countAllMap.get("total"));
        statistics.add(null);
        statistics.add(null);
        data.add(statistics);
        return data;
    }
}
